<template>
    <div>
      <!-- 子组件模板 -->
      <h3>子组件</h3>
      <div>
        <!-- 输入框绑定到本地计算属性，当输入变化时会触发更新事件 -->
        <div class="input-group">
          <label>文本输入：</label>
          <!--  v-model="inputValue"  等同于 :value="inputValue"   @input="updateValue($event.target.value)"   -->
          <input 
            type="text" 
            :value="inputValue" 
           @input="updateValue($event.target.value)"
            placeholder="请输入文本"
          />
        </div>

        <!-- 数字输入示例 -->
        <div class="input-group">
          <label>数字输入：</label>
          <input 
            type="number" 
            :value="count" 
            @input="updateCount(Number($event.target.value))" 
            placeholder="请输入数字"
          />
        </div>

        <!-- 复选框示例 -->
        <div class="input-group">
          <label>
            <input 
              type="checkbox" 
              :checked="checked" 
              @change="updateChecked($event.target.checked)" 
            />
            选中状态
          </label>
        </div>
      </div>
    </div>
  </template>
  
  <script lang="ts" setup>
  /**
   * v-model 组件通信详解 - 子组件部分
   * 
   * 1. 概念：
   *    v-model 是 Vue 中实现双向绑定的指令，在组件上使用时，
   *    它是 props 和事件的语法糖，用于简化父子组件间的双向数据流。
   * 
   * 2. 基本原理：
   *    - 在 Vue 3 中，组件上的 v-model 默认会：
   *      a. 向子组件传递一个名为 modelValue 的 prop
   *      b. 监听子组件触发的 update:modelValue 事件
   * 
   * 3. 子组件实现 v-model 的方式：
   *    3.1 接收 modelValue prop
   *    3.2 在值变化时触发 update:modelValue 事件
   */
  
  import { computed } from 'vue';
  
  // 定义 props，接收父组件传递的值
  const props = defineProps<{
    // 默认的 v-model 绑定值
    modelValue: string;
    // 自定义 v-model 名称（如 v-model:count）
    count: number;
    // 另一个自定义 v-model（如 v-model:checked）
    checked: boolean;
  }>();
  
  // 定义要触发的事件
  const emit = defineEmits<{
    // 默认的 v-model 更新事件
    (e: 'update:modelValue', value: string): void;
    // 自定义 v-model 的更新事件
    (e: 'update:count', value: number): void;
    // 另一个自定义 v-model 的更新事件
    (e: 'update:checked', value: boolean): void;
  }>();
  
  /**
   * 4. 使用计算属性处理 v-model：
   *    - 可以使用计算属性创建双向绑定
   *    - get: 返回 props 中的值
   *    - set: 触发更新事件
   */
  
  // 使用计算属性简化 v-model 处理（可选方式）
  const inputValue = computed({
    get: () => props.modelValue,
    set: (value) => emit('update:modelValue', value)
  });
  
  // 直接使用方法触发更新事件
  function updateValue(value: string) {
    emit('update:modelValue', value);
  }
  
  function updateCount(value: number) {
    emit('update:count', value);
  }
  
  function updateChecked(value: boolean) {
    emit('update:checked', value);
  }
  
  /**
   * 5. v-model 修饰符：
   *    - 父组件可以使用修饰符如 v-model.trim
   *    - 子组件可以通过 modelModifiers prop 访问这些修饰符
   * 
   * 示例：
   * const props = defineProps({
   *   modelValue: String,
   *   modelModifiers: { default: () => ({}) }
   * });
   * 
   * // 处理 trim 修饰符
   * function updateValue(e) {
   *   let value = e.target.value;
   *   if (props.modelModifiers.trim) {
   *     value = value.trim();
   *   }
   *   emit('update:modelValue', value);
   * }
   * 
   * 6. 多个 v-model 绑定：
   *    - Vue 3 支持在同一组件上使用多个 v-model
   *    - 使用 v-model:name 的语法指定不同的绑定
   */
  </script>
  
  <style scoped>
  /* 子组件样式 */
  div {
    background: linear-gradient(to right, #f6d365, #fda085);
    border-radius: 12px;
    padding: 20px;
    margin: 15px 0;
    box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
    transition: all 0.3s ease;
  }
  
  div:hover {
    transform: translateY(-5px);
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
  }
  
  h3 {
    color: #ffffff;
    font-size: 22px;
    margin-bottom: 15px;
    text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.2);
    font-weight: 500;
    letter-spacing: 1px;
  }

  .input-group {
    margin-bottom: 15px;
    display: flex;
    align-items: center;
  }

  label {
    color: white;
    font-weight: 500;
    margin-right: 10px;
    min-width: 80px;
  }

  input[type="text"],
  input[type="number"] {
    padding: 8px 12px;
    border: none;
    border-radius: 6px;
    font-size: 16px;
    background-color: rgba(255, 255, 255, 0.9);
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
    width: 200px;
  }

  input[type="checkbox"] {
    margin-right: 8px;
    transform: scale(1.2);
  }

  input:focus {
    outline: none;
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.5);
  }
  </style>